/********************************************************************************************************************************
 * 《C ++ Primer》第五版中文版，读书笔记：按照书中的的示例源码和每一个小章节的课后习题，自己动手写代码实现，作为联系和测试。
 * Date: 2024-03-25 09:46
 * Author: dimon.chen 
 * EMali: 1181302388@qq.com 
 * 
 * 章节: 第二章 变量和基本类型
 *       2.4.2 指针和const
 * 
 ********************************************************************************************************************************/

#include <iostream>

int main(int argc, char *argv[])
{
    ///
    /// 练习 2.4.2
    /// 2.27 下面的那些初始化语句是合法的？请说明原因
    /// 
    ///
#if 0
    int i2 = 4;
    int i = -1, &r = 0;         //错误: i是一个普通引用，其初始值不能是字面值
    int *const p2 = &i2;        //正确：p2是一个常量指针，常量指针必须初始化。常量指针的类型必须和它
                                //指向的类型一致。但有两种例外：1. 常量指针可以指向非常量型相同类型的对象
    const int i = -1, &r = 0;   //正确: 是一个普通int 常量
                                //      r是一个指向 const int 的引用（常量引用）
                                //      常量引用的初始值可以是任意复杂的表达式，只要表达式的计算结果
                                //      可以转化为其引用的类型
                                //      尤其：常量引用可以绑定非常量型对象，字面值，甚至一个表达式，
                                //      

    const int *const p3 = &i2;  //正确：p3是指向int型常量的常量指针
                                //      常量指针必须被初始化，在其定义之后常量指针的指向的对象就不能修改
                                //      指针常量的可以指向非常量类型
                                //      与常量引用（执行常量的引用）类似常量指针值限定了指针本身的指向不能修改
                                //      能否通过指针修改它指向的对象完全取决于它指向对象的类型
                                //      p3是指向int常量的常量指针，其指针本身的值和指向的值都不能通过指针对象修改
                                //      指针的对象必须和它指向的对象类型严格匹配
    const int *p1 = &i2;        //正确：p1是指向int型常量的指针，不能通过指针来修改它指向的对象
                                //      但并不以为者在程序的接下来执行过程中不能修改指针指向其他对象。

    const int & const r2;       //错误：因为引用不是对象，所以不存在'常量引用'

    const int i2 = i, &r = i;   //正确：i2是int常量，其初始值从i拷贝
                                //      r是引用，其指向 int型常量 （执行 const 的引用）通常简称为“常量引用"，
                                //      引用必须被初始化，常量引用可以绑定到非常量引用，字面值，甚至一个表达式


#endif 

    ///
    /// 练习 2.4.2
    /// 2.28 说明下面这些定义时什么意思，挑出其中不合法的。
    /// 
    ///
    int i, *const cp = &i;           //错误：i为int型对象， cp为常量指针，指向int型对象，常量指针定义时必须初始化
    int *p1, *const p2 = &i;         //错误：p1为指向int型指针，p2为常量指针，指向int型对象，常量指针必须在定义时初始化
    const int ic = 0, &r = ic;      //正确：ic为int型常量；(答错了)
                                    //错误: ic为int型常量，常量对象在定义之后其值就不能发生改变，所以常量在定义时必须初始化。
                                    //错误： r为引用，引用在定义时必须初始化，r指向ic，r为指向 cont int 对象的引用（常量引用）
    const int *const p3 = &i;       //错误：p3为指向 const int 的常量指针，常量指针定义时必须初始化
    const int *p = &ic;             //p为指向 const int （int型常量）的指针


    ///
    /// 练习 2.4.2
    /// 2.29 假设已经有上一个练习中定义的哪些变量，这下面哪些语句是合法的？请说明原因。
    /// 
    ///

    i = ic;         //正确： i为int型对象，从常量ic中拷贝值赋值给i
    p1 = p3;        //错误:  p1为执行int
                    //这个是错误还是正确哪？指针赋值，指针的类型必须相同
                    //编译了一下结果为不正确，不能把一个 cont int * 指针转换为 int * 指针
    p1 = &ic;       //错误：指针的类型必须和它指向的类型匹配
                    //      p1是一个指向int型的指针，而ic是一个 const int 对象
    p3 = &ic;       //错误: p3是指向int 常量的常量指针，在常量指针定义初始化之后，其值不能被修改指向其他对象
    p2 = p1;        //错误： p2 是指向int对象的常量指针，p1是指向int的指针。
                    //      常量指针定义是必须初始化，定义之后就不能修改其指向新的对象
    ic  = *p3;      //错误： ic为int型常量，常量必须在定义时初始化，定义之后常量的值不能修改
    
    

}
